<?php
/*
*All rights reserved: Json.
*Links:http://www.liyaoquan.cn.
*Links:http://imarkchina.cn.
*Links:http://www.imarkchina.cn.
*/

Abstract Class J {

	/**
	* 初始化: debug信息, 时差, 提交的请求, 路由
	* 在不需要加载控制器时调用
	*/
	Public Static function init() {
		if (C('GZIP') && !ob_get_contents()) ob_start('ob_gzhandler');
		if (C('DEBUG')) set_error_handler(array('Debug', 'catcher'));
		if (C('DEBUG')) register_shutdown_function(array('Debug', 'display'));
		date_default_timezone_set(C('TIMERPC'));
		self::parseUrl();
	}

	/**
	* 分发控制器文件
	* @param string 控制器路径
	*/
	Public Static function run() {
		self::init();
		$models = isset($_GET['m']) ? ucfirst($_GET['m']) : APPNAME;
		$className = isset($_GET['c']) ? ucfirst($_GET['c']).'Action' : 'IndexAction';
		$action = isset($_GET['a']) ? $_GET['a'] : 'index';
		$allClass = CONTROLLER.$models.'/';
		$allMode = MODEL.$models.'/';
		define('MODELSNAME', $models);
		define('CONTROLLERNAME', (isset($_GET['c']) ? ucfirst($_GET['c']) : 'Index'));
		define('ACTIONNAME', $action);
		$file = CONTROLLER.$models.'/'.$className.'.php';
		try{
			if (!file_exists($file)) {
				self::debug(__METHOD__.' [无法加载控制器文件: '.$file.']');
				include_once JSON_PATH.'/Common/404.php';
				self::debug(__METHOD__.' [自动加载控制器文件: '.JSON_PATH.'/Common/404.php]');
				httpHeader('404');
				return;
			}
			//注册类自动加载路径
			self::registerAutoload($allClass);
			self::registerAutoload($allMode);
			$Controller = new $className();
			$filters = array_merge(get_class_methods('Template'), get_class_methods('Action'));
			$filters = array_unique($filters);
			if (!is_callable(array($Controller, $action)) || in_array($action, $filters)) {
				self::debug(__METHOD__.' [加载失败: '.get_class($Controller).'::'.$action.']');
				include_once JSON_PATH.'/Common/404.php';
				self::debug(__METHOD__.' [自动调用: '.JSON_PATH.'/Common/404.php]');
				httpHeader('404');
				return;
			}
			$Controller->$action();
		} catch (Exception $e) {
			if (C('DEBUG')) {
				self::debug('<font color="red">'.$e->getMessage().'</font>');
			} else {
				httpHeader('404');
				return;
			}
		}
	}

	Private Static $_autoload = array();
	/**
	* 注册类自动加载路径
	* @param mixed 多个路径格式为数组 eg: array('path1', 'path2')
	* @param bool 真则调用spl_autoload_register函数, 首次调用需为真
	*/
	Public Static function registerAutoload($path, $append = false) {
		if (is_array($path)) {
			self::$_autoload = array_merge(self::$_autoload, $path);
		} else {
			self::$_autoload[] = $path;
		}
		self::$_autoload = array_unique(self::$_autoload);
		if ($append == true) spl_autoload_register(array('self', '_autoload'));
	}

	/**
	 * 自动注册类
	 * @param  [type] $class [description]
	 * @return [type]        [description]
	 */
	Private Static function _autoload($class) {
		foreach (self::$_autoload as $path) {
			$file = $path.'/'.$class.'.php';
			if (is_file($file)) {
				include $file;
				self::debug('<b>'.$class.'.php</b> 类', 1);
				if (!class_exists($class)) exit('未定义 '.$class.' 类');
				return;
			}
		}
		echo '<p>类'.$class.'加载失败</p>';
		echo '<p>搜索路径: </p>';
		echo '<p>'.join('<br />', self::$_autoload).'</p>';
		exit();
	}

	Private Static $_class = array();
	/**
	* 获取一个对象(单例模式)
	* @param  [type] $class [description]
	* @return [type]        [description]
	*/
	Public Static function loadClass($class) {
		$class = ucfirst($class);
		if (!isset(self::$_class[$class])) self::$_class[$class] = new $class();
		return self::$_class[$class];
	}

	/**
	* 添加一条debug信息
	* @param string
	* @param int 1为包含文件的信息
	*/
	Public Static function debug($message, $type = 0) {
		if (C('DEBUG')) Debug::add($message, $type);
	}

	/**
	* 获取根URL
	* @return string
	*/
	Public Static function getRootUrl() {
		if (!isset($_SERVER['DOCUMENT_ROOT'])) {
			if (isset($_SERVER['SCRIPT_FILENAME'])) {
				$_SERVER['DOCUMENT_ROOT'] = str_replace('\\', '/', substr($_SERVER['SCRIPT_FILENAME'], 0, 0 - strlen($_SERVER['PHP_SELF'])));
			}
		}
		if (empty($_SERVER['DOCUMENT_ROOT']) && isset($_SERVER['PATH_TRANSLATED'])) {
			$_SERVER['DOCUMENT_ROOT'] = str_replace('\\', '/', substr(str_replace('\\\\', '\\', $_SERVER['PATH_TRANSLATED']), 0, 0 - strlen($_SERVER['PHP_SELF'])));
		}
		$result = str_replace(str_replace('\\', '/', $_SERVER['DOCUMENT_ROOT']), '', str_replace('\\', '/', ROOT_PATH));
		if (isset($_SERVER['SERVER_SOFTWARE']) && stristr($_SERVER['SERVER_SOFTWARE'], 'IIS')) {
			if (mb_detect_encoding($result) == 'GBK') $result = mb_convert_encoding($result, 'UTF-8', 'GBK');
		}
		return $result ? '/'.ltrim($result, '/') : '';
	}

	/**
	* 获取默认模板路径
	* @return string
	*/
	Public Static function getTemplateUrl() {
		return str_replace(ROOT_PATH, ROOT_URL, TEMPLATE.MODELSNAME.'/'.C('TPLFILE'));
	}

	/**
	* 获取模板根目录路径
	* @return [type] [description]
	*/
	Public Static function getTpl(){
		return str_replace(ROOT_PATH, ROOT_URL, TEMPLATE);
	}

	/**
	* 获取运行耗时
	* @return string
	*/
	Public Static function getRuntime() {
		$stopTime = microtime(true);
		return number_format(($stopTime - BEGIN_TIME), 4);
	}

	/**
	* 获取运行消耗内存
	* @return string
	*/
	Public Static function getRunMemory() {
		$format = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');
		$pos = 0;
		$stopMemory = memory_get_usage();
		$size = $stopMemory - BEGIN_MEMORY;
		while ($size >= 1024) {
			$size /= 1024;
			$pos++;
		}
		return round($size, 2).' '.$format[$pos];
	}

	/**
	* 获取域名
	* @return string
	*/
	Public Static function getDomain() {
		$host = '';
		$protocol = (isset($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) != 'off')) ? 'https://' : 'http://';
		if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
			$host = $_SERVER['HTTP_X_FORWARDED_HOST'];
		} else if (isset($_SERVER['HTTP_HOST'])) {
			$host = $_SERVER['HTTP_HOST'];
		} else {
			if (isset($_SERVER['SERVER_PORT'])) {
				$port = ':'.$_SERVER['SERVER_PORT'];
				if ((':80' == $port && 'http://' == $protocol) || (':443' == $port && 'https://' == $protocol))
					$port = '';
			} else {
				$port = '';
			}
			if (isset($_SERVER['SERVER_NAME'])) {
				$host = $_SERVER['SERVER_NAME'].$port;
			} else if (isset($_SERVER['SERVER_ADDR'])) {
				$host = $_SERVER['SERVER_ADDR'].$port;
			}
		}
		return $protocol.$host;
	}

	/**
	* 递归创建目录
	* @param string 目录路径
	* @param int 目录权限
	* @return bool
	*/
	Public Static function makeDir($dir, $mode = 0777) {
		if (!is_dir($dir)) {
			self::makeDir(dirname($dir), $mode);
			return mkdir($dir, $mode);
		}
		return true;
	}

	/**
	* 根据配置文件分发路由
	* @return [type] [description]
	*/
	Public Static function parseUrl(){
		if (C('URLREWRITE')) {
			$serverpathinfo = isset($_SERVER['PATH_INFO']) ? trim($_SERVER['PATH_INFO'], '/') : null;
			if (!empty($serverpathinfo)) {
				$paths = explode(C('URLSPACE'), $serverpathinfo, 2);
				$getmodels = ucfirst($paths[0]);
			} else {
				$getmodels = APPNAME;
			}
		} else {
			$getmodels = ucfirst($_GET['m']);
		}
		
		$applist = explode(',', C('APPLIST'));
		foreach ($applist as $k => $v) {
			$applist[$k] = ucfirst($v);
		}
		if (in_array_case($getmodels, $applist)) {
			if (file_exists(COMMON.$getmodels.'/config.php')) {
				C(include COMMON.$getmodels.'/config.php');
			}
		} else {
			if (file_exists(COMMON.APPNAME.'/config.php')) {
				C(include COMMON.APPNAME.'/config.php');
			}
		}
		if (C('URLREWRITE')){
			if (C('URLROUTE')) {
				$urlrouteon = '/'.str_replace(array(C('URLSPACE'), C('URLFIX')), array('/', ''), $serverpathinfo);//去掉配置文件中(URLFIX)后缀名
				foreach (C('URLRULES') as $pattern => $controller) {
					if (preg_match('#^/?'.$pattern.'/?$#', $urlrouteon, $match)) {  //取得控制器与方法
						$models = $controller[0];
						array_shift($controller);
						$controllers = $controller[0];
						array_shift($controller);
						$actions = $controller[0];
						array_shift($controller);
						break;
					}
				}
				if (empty($match)) {
					include_once JSON_PATH.'/Common/404.php';
					if (C('DEBUG')) {
						self::debug(__METHOD__.' [加载失败: '.$serverpathinfo.'::'.$serverpathinfo.']');
						self::debug(__METHOD__.' [自动加载控制器文件: '.JSON_PATH.'/Common/404.php]');
					}
					httpHeader('404');
					exit();
				}
				$pinfo = explode(C('URLSPACE'), $serverpathinfo);
				foreach ($pinfo as $key => $value) {
					$pinfo = str_replace(C('URLFIX'), '', $pinfo);
				}
				for($i=0; $i<count($pinfo); $i+=2){
					$_GET[$pinfo[$i]] =  isset($pinfo[$i+1]) ? $pinfo[$i+1] : 1;
				}
			} else {
				$pathinfo = explode(C('URLSPACE'), $serverpathinfo);
				foreach ($pathinfo as $key => $value) {
					$pathinfo = str_replace(C('URLFIX'), '', $pathinfo);
				}//去掉配置文件中(URLFIX)后缀名
				//默认是index模块
				$models = (!empty($pathinfo[0]) ? $pathinfo[0] : APPNAME);
				array_shift($pathinfo);//将数组开头的单元移出数组
				//默认是index控制器
				$controllers = (!empty($pathinfo[0]) ? $pathinfo[0] : 'index');
				array_shift($pathinfo); //将数组开头的单元移出数组
				//默认是index动作
				$actions = (!empty($pathinfo[0]) ? $pathinfo[0] : 'index');
				array_shift($pathinfo); //再将将数组开头的单元移出数组
				for($i=0; $i<count($pathinfo); $i+=2){
					$_GET[$pathinfo[$i]] = isset($pathinfo[$i+1]) ? $pathinfo[$i+1] : 1;
				}
			}
			$_GET['m'] = !empty($models) ? $models : APPNAME;     //默认是index模块
			$_GET['c'] = !empty($controllers) ? $controllers : 'index';    //默认是index控制
			$_GET['a'] = !empty($actions) ? $actions : 'index';   //默认是index动作
		} else {
			foreach ($_GET as $key => $value) {
				$_GET = str_replace(C('URLFIX') , '', $_GET);
			}//去掉配置文件中(URLFIX)后缀名
			$_GET['m'] = !empty($_GET['m']) ? $_GET['m'] : APPNAME;     //默认是index模块
			$_GET['c'] = !empty($_GET['c']) ? $_GET['c']: 'index';    //默认是index控制
			$_GET['a'] = !empty($_GET['a']) ? $_GET['a'] : 'index';   //默认是index动作
		}
	}
}